#include "Parser.h"
#include "RuntimeException.h"
#include <iostream>

Parser::Parser(vector<Token*> inputVect): input(inputVect) {
		TokenEnd* end = new TokenEnd(); 
        opStack.push_back(end);
}

list<Token*> Parser::getPostFix() const{
        return postFix;
}

list<Token*> Parser::getOpStack() const{
        return opStack;
}

void Parser::printfunc() {
	list<Token*>::iterator p = postFix.begin();
	for (; p!=postFix.end(); p++) {
		if((*p)->getId() == 'd'){
			cout << "Value: " << (*p)->getValue() << endl;
		}
		else {
		cout<< (*p)->getId()<<endl;
		}
	}
}

void Parser::infixToPostfix(){
		if (input.size() == 0) throw RuntimeException("No input");
        for (int i = 0; i < input.size(); i++){
                Token* inp = input[i];
				char id = inp->getId();
                if (id =='d'){ 
                        postFix.push_back(inp);
						continue;
                }
                if(id =='#'){ // pop everything up to the END token and enqueue
					while (!opStack.empty() && ((opStack.back())->getId())!='#') {
						postFix.push_back(opStack.back());
						opStack.pop_back();
					}
					opStack.pop_back();
					return;
					//pop #?
                }
                if(id == '('){
                        opStack.push_back(inp);
						continue;
                }
                if(id == ')'){
					while (!opStack.empty() && ((opStack.back())->getId())!='(') {
						postFix.push_back(opStack.back());
						opStack.pop_back();
						//pop everything up to left paren (ignore paren)  and enqueue
					}
					if (!opStack.empty() && ((opStack.back())->getId())=='(') {
						opStack.pop_back();
					}
					continue;
                }
				else{  // operator

					Token* temp = opStack.back(); 
					while (temp->getStackPrior() >= inp->getInPrior()) { //pop from stack into queue those operators with stack priority > input priority
						postFix.push_back(temp);
						opStack.pop_back();
						if (!opStack.empty()) temp = opStack.back();
						else break;
					}
					opStack.push_back(inp); //push current operator into stack
				}
		}
		Token* temp = opStack.back(); 
		while (temp->getId() != '#')
		{
				postFix.push_back(temp);
				opStack.pop_back();
				temp = opStack.back();
		}

}

